<script setup>
import {
    reactive,
    ref,
    onMounted,
    getCurrentInstance,
    nextTick,
    watch,
    computed, onUnmounted
} from "vue";
import { useRoute, useRouter } from "vue-router";
import { showLoadingToast, showToast, closeToast, showSuccessToast } from "vant";
import Recorder from "recorder-core";
import "recorder-core/src/engine/mp3";
import "recorder-core/src/engine/mp3-engine";
import "recorder-core/src/engine/pcm";
import { marked } from "marked";
import sanitizeHtml from "sanitize-html";
import huatong from "@/assets/img/huatong.png";
import { useChatStore } from "@/store/index";
import CryptoJS from "crypto-js"
import IatService from "@/utils/index" // 修改导入路径

const store = useChatStore();
const {
    proxy: { $http },
} = getCurrentInstance();
const route = useRoute();
const router = useRouter();

const props = defineProps({
    socketData: {
        type: Object,
        default: null,
    },
    loading: {
        type: Object,
        default: null,
    },
});

// 讯飞语音听写配置
const appId = '7cf019c8';
const apiKey = 'a0a7c5cc3d0c4d5a8fda57fa379d2bbc';
const apiSecret = 'YjY4YmRmMjViN2E1ZDk5NDU1MjFmOTJm';
const iatService = ref(null);

const dataVal = reactive({
    huatong,
    isVoiceMode: false,
    recording: false,
    inputValue: "",
    showMedia: false,
    recordingTimer: null,
    formData: {},
    isRecordingSupported: true,
    messages: [],
    scrollTop: 0,
    showForm: false,
    recorder: null,
    showRecordingPopup: false,
    isCanceling: false,
    touchStartY: 0,
    recordingDuration: 0,
    showKeyboardIcon: true,
    volumeLevel: 0,
    isAIResponding: false,
    currentResponse: "",
    abortController: null,
    conversationId: null,
    iatStatus: '准备就绪',
    iatResult: '',
    debugMode: true, // 调试模式
});

const BTN_CONTROL = ref(null)

// 配置 marked
marked.setOptions({
    breaks: true,
    gfm: true,
});

const emits = defineEmits(["send", "add", "command"]);

// 安全地渲染 Markdown
const renderMarkdown = (markdown) => {
    if (!markdown) return "";
    const html = marked(markdown);
    return sanitizeHtml(html, {
        allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img", "h1", "h2", "h3", "h4"]),
        allowedAttributes: {
            ...sanitizeHtml.defaults.allowedAttributes,
            a: ["href", "name", "target", "rel"],
            img: ["src", "alt", "title"],
        },
        allowedSchemes: ["http", "https", "mailto", "data"],
        transformTags: {
            a: (tagName, attribs) => {
                if (attribs.href && attribs.href.startsWith("http")) {
                    return {
                        tagName: "a",
                        attribs: {
                            ...attribs,
                            target: "_blank",
                            rel: "noopener noreferrer",
                        },
                    };
                }
                return { tagName, attribs };
            },
        },
    });
};

// 初始化讯飞语音服务
const initIatService = () => {
    iatService.value = new IatService(appId, apiKey, apiSecret);

    // 设置回调函数
    iatService.value.setCallbacks(
        (result) => {
            dataVal.iatResult = result;
            console.log('识别结果更新:', result);
            if (result && result.trim()) {
                dataVal.inputValue = result;
            }
        },
        (status) => {
            dataVal.iatStatus = status;
            console.log('状态更新:', status);
        },
        // 新增：WebSocket状态回调
        (wsStatus, wsStatusText) => {
            console.log('WebSocket状态:', wsStatus, wsStatusText);
        }
    );
};

// 检查浏览器是否支持录音
const checkRecordingSupport = async () => {
    try {
        dataVal.isRecordingSupported = !!(
            navigator.mediaDevices &&
            navigator.mediaDevices.getUserMedia &&
            (window.AudioContext || window.webkitAudioContext)
        );

        if (!dataVal.isRecordingSupported) {
            showToast("浏览器不支持录音基础API");
            return false;
        }

        if (typeof Recorder === "undefined") {
            showToast("录音核心库加载失败");
            return false;
        }

        const devices = await navigator.mediaDevices.enumerateDevices();
        const hasMicrophone = devices.some(
            (device) => device.kind === "audioinput"
        );
        if (!hasMicrophone) {
            showToast("未检测到麦克风设备");
            return false;
        }

        const stream = await navigator.mediaDevices.getUserMedia({
            audio: true,
        });
        stream.getTracks().forEach((track) => track.stop());

        return true;
    } catch (error) {
        console.error("录音支持检查失败:", error);
        let errorMsg = "无法访问麦克风";
        if (error.name === "NotAllowedError") {
            errorMsg = "麦克风权限被拒绝";
        } else if (error.name === "NotFoundError") {
            errorMsg = "未找到麦克风设备";
        }
        showToast(errorMsg);
        return false;
    }
};

// 初始化录音器
// 修改initRecorder函数
const initRecorder = async () => {
    try {
        dataVal.recorder = new Recorder({
            type: "pcm",
            sampleRate: 16000,
            bitRate: 16,
            compiling: true,
            onProcess: (buffers, powerLevel) => {
                dataVal.volumeLevel = Math.floor(powerLevel * 100);

                if (iatService.value && dataVal.recording) {
                    const pcmData = buffers[0];

                    // 添加详细的调试信息
                    console.log('🎙️ 处理音频数据:', {
                        length: pcmData.length,
                        type: pcmData.constructor.name,
                        first10: Array.from(pcmData).slice(0, 10)
                    });

                    // 确保发送正确的数据格式
                    if (pcmData instanceof Float32Array) {
                        // Recorder-core返回的是Float32Array，需要转换
                        const int16Data = new Int16Array(pcmData.length);
                        for (let i = 0; i < pcmData.length; i++) {
                            int16Data[i] = Math.max(-32768, Math.min(32767, pcmData[i] * 32768));
                        }
                        iatService.value.sendAudioData(int16Data);
                    } else {
                        iatService.value.sendAudioData(pcmData);
                    }
                }
            },
        });

        const stream = await navigator.mediaDevices.getUserMedia({
            audio: {
                sampleRate: 16000,
                channelCount: 1,
                echoCancellation: true,
                noiseSuppression: true
            },
        });

        await new Promise((resolve, reject) => {
            dataVal.recorder.open(
                () => {
                    console.log('✅ 录音器打开成功');
                    resolve();
                },
                (error) => {
                    console.error('❌ 录音器打开失败:', error);
                    reject(error);
                }
            );
        });

        return true;
    } catch (error) {
        console.error("❌ 录音初始化失败:", error);
        showToast("录音初始化失败");
        return false;
    }
};

// 开始录音
const startRecording = async (event) => {
    if (!dataVal.isRecordingSupported) return;

    try {
        if (!iatService.value) {
            initIatService();
        }

        console.log('开始连接讯飞WebSocket...');
        const connected = iatService.value.startRecording();
        if (!connected) {
            showToast("连接语音识别服务失败");
            return;
        }
        console.log('讯飞WebSocket连接成功');

        if (!dataVal.recorder) {
            console.log('初始化录音器...');
            const initSuccess = await initRecorder();
            if (!initSuccess) return;
            console.log('录音器初始化成功');
        }

        dataVal.recorder.start();
        dataVal.recording = true;
        dataVal.showRecordingPopup = true;
        dataVal.isCanceling = false;
        dataVal.recordingDuration = 0;
        dataVal.iatResult = '';

        dataVal.recordingTimer = setInterval(() => {
            dataVal.recordingDuration++;
            if (dataVal.recordingDuration >= 60) {
                stopRecording();
            }
        }, 1000);

        console.log('录音开始');
    } catch (error) {
        console.error("开始录音失败:", error);
        showToast("开始录音失败: " + error.message);
    }
};

// 处理触摸移动（用于上滑取消）
const handleTouchMove = (event) => {
    if (!dataVal.recording) return;

    const touchY = event.touches[0].clientY;
    const deltaY = dataVal.touchStartY - touchY;

    if (deltaY > 50) {
        dataVal.isCanceling = true;
    } else if (deltaY < 30) {
        dataVal.isCanceling = false;
    }
};

// 停止录音
const stopRecording = () => {
    if (!dataVal.recording) return;

    clearInterval(dataVal.recordingTimer);
    dataVal.recording = false;
    dataVal.showRecordingPopup = false;

    document.removeEventListener("touchmove", handleTouchMove);

    if (iatService.value) {
        iatService.value.stopRecording();
    }

    if (dataVal.recorder) {
        dataVal.recorder.stop(
            async (blob, duration) => {
                if (dataVal.isCanceling) {
                    showToast("已取消录音");
                    return;
                }

                console.log('录音停止，识别结果:', dataVal.iatResult);

                if (dataVal.iatResult && dataVal.iatResult.trim()) {
                    addMessage(dataVal.iatResult, true, true);
                    sendMessage(dataVal.iatResult);
                } else {
                    showToast("未识别到语音内容");
                    console.warn('未识别到内容，可能的原因:', {
                        recordingDuration: duration,
                        result: dataVal.iatResult
                    });
                }

                dataVal.recorder.close();
                dataVal.recorder = null;
            },
            (error) => {
                console.error("停止录音失败:", error);
                showToast("停止录音失败");
            }
        );
    }
};

// 发送消息给AI接口
const sendMessage = async (text) => {
    const item = {
        inputs: {},
        query: text,
        conversationId: dataVal.conversationId,
        response_mode: "blocking",
        user: store.userInfo?.userId.toString() ?? "abc-123",
        files: [],
        aimodelToken: store.modelToken,
    };

    dataVal.abortController = new AbortController();
    dataVal.isAIResponding = true;
    dataVal.currentResponse = "";

    try {
        const res = await $http.post("/jcsz/chatSendMessage", item, {
            signal: dataVal.abortController.signal,
        });

        if (res && res.data) {
            const item = JSON.parse(res.data.data);

            if (!dataVal.conversationId) {
                dataVal.conversationId = item.conversation_id;
            }

            if (item.answer.startsWith("cmd")) {
                await handleCommand(item.answer);
            } else {
                addMessage(item.answer, false, false);
            }
        } else {
            addMessage("抱歉，我没有理解您的问题，请换个方式提问。", false, false);
        }
    } catch (error) {
        if (error.name !== "AbortError") {
            console.info("请求失败: " + error.message);
            addMessage("网络请求失败，请稍后重试。", false, false);
        }
    } finally {
        dataVal.isAIResponding = false;
        dataVal.abortController = null;
        dataVal.currentResponse = "";
        dataVal.inputValue = "";
    }
};

const clickText = (text) => {
    dataVal.inputValue = text;
    sendText();
};

// 发送文本消息
const sendText = (text) => {
    const item = text ?? dataVal.inputValue;
    if (!item.trim()) return;
    sendMessage(item);
    addMessage(item, true, false);
};

// 切换语音/文字模式
const toggleMode = () => {
    dataVal.isVoiceMode = !dataVal.isVoiceMode;
};

// 添加消息到聊天窗口
const addMessage = (text, isSent, isVoice = false) => {
    if (text) {
        const processedText = isSent ? text : renderMarkdown(text);
        const message = {
            text: processedText,
            isSent,
            time: new Date().toLocaleTimeString([], {
                hour: "2-digit",
                minute: "2-digit",
            }),
            isVoice,
            showFrom: !isSent && text.includes("表单"),
            rawText: text,
        };
        dataVal.messages.push(message);
    }
    emits("add", dataVal.messages || null, isSent, false);
};

// 监听socket数据和路由变化
watch(
    [() => props.socketData],
    ([newVal]) => {
        if (newVal?.type === "request") {
            sendText(newVal.data);
        } else if (newVal?.type === "show") {
            addMessage(newVal?.data, false, false);
        } else if (newVal?.type === "command") {
            handleCommand(newVal.data);
        }
    },
    {
        immediate: true,
    }
);

defineExpose({
    addMessage,
    sendText,
    clickText,
    toggleMode,
});

onMounted(async () => {
    await checkRecordingSupport();
    initIatService();

    document.addEventListener("touchmove", handleTouchMove);
});

onUnmounted(() => {
    if (dataVal.recorder) {
        dataVal.recorder.close();
    }
    if (dataVal.abortController) {
        dataVal.abortController.abort();
    }
    if (iatService.value) {
        iatService.value.destroy(); // 使用新的destroy方法
    }
    document.removeEventListener("touchmove", handleTouchMove);
});
</script>

<template>
    <div class="ai-bottom">
        <!-- 调试信息 -->
        <div v-if="dataVal.debugMode" class="debug-info">
            <div>状态: {{ dataVal.iatStatus }}</div>
            <div>录音中: {{ dataVal.recording }}</div>
            <div>识别结果: {{ dataVal.iatResult }}</div>
        </div>

        <div class="aibox d-flex align-items-center">
            <!-- 语音模式 -->
            <div class="voice-container">
                <van-icon :name="dataVal.huatong" size="26" class="mode-switch-icon" />
                <div class="voice-btn" ref="BTN_CONTROL" :class="{ canceling: dataVal.isCanceling }"
                    @touchstart="startRecording" @touchend="stopRecording">
                    {{ dataVal.iatStatus }}
                </div>
            </div>
        </div>

        <!-- 显示识别结果 -->
        <div v-if="dataVal.iatResult" class="recognition-result">
            <div class="result-label">识别结果:</div>
            <div class="result-text">{{ dataVal.iatResult }}</div>
        </div>

        <div class="tips mt-2 text-c">内容由AI生成，仅供参考</div>

        <!-- 录音提示弹窗 -->
        <van-popup v-model:show="dataVal.showRecordingPopup" round position="center"
            :style="{ height: '30%', width: '80%' }">
            <div class="recording-popup">
                <div class="volume-indicator">
                    <div v-for="i in 5" :key="i" class="volume-bar" :class="{
                        active: dataVal.volumeLevel > (i - 1) * 20,
                    }" :style="{ height: `${i * 15}px` }"></div>
                </div>

                <div class="recording-status d-flex align-items-center">
                    <van-icon name="delete" size="24" v-if="dataVal.isCanceling" />
                    <van-icon name="volume-o" size="24" v-else />
                    <div class="status-text ml-2">
                        {{
                            dataVal.isCanceling
                                ? "上滑取消录音"
                                : "录音中..."
                        }}
                    </div>
                </div>

                <div class="recording-timer">
                    {{ dataVal.recordingDuration }}秒
                </div>

                <div class="recording-tip">最长可录音60秒</div>
            </div>
        </van-popup>
    </div>
</template>

<style scoped lang="scss">
.ai-bottom {
    width: 100%;
    box-sizing: border-box;
    padding: 0 20px;

    .aibox {
        background-color: #fff;
        padding: 0 6px;
        border-radius: 20px;
        box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
    }

    .debug-info {
        background: #f5f5f5;
        padding: 10px;
        border-radius: 8px;
        margin-bottom: 10px;
        font-size: 12px;
        color: #666;
    }

    .recognition-result {
        margin-top: 10px;
        padding: 10px;
        background-color: #f9f9f9;
        border-radius: 8px;

        .result-label {
            font-weight: bold;
            margin-bottom: 5px;
            color: #333;
        }

        .result-text {
            color: #666;
        }
    }

    .tips {
        color: #999;
    }
}

.voice-container {
    display: flex;
    align-items: center;
    width: calc(100% - 40px);
    height: 50px;
    padding: 0 10px;

    .mode-switch-icon {
        margin-right: 15px;
    }

    .voice-btn {
        flex: 1;
        height: 40px;
        margin: 0 10px;
        background: #f0f0f0;
        border-radius: 25px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 16px;
        color: #333;
        font-weight: 500;
        transition: all 0.3s;

        &:active {
            background-color: #e0e0e0;
        }

        &.canceling {
            background-color: #ffeceb;
            color: #ff4d4f;
        }
    }
}

/* 录音弹窗样式 */
.recording-popup {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;

    .volume-indicator {
        display: flex;
        align-items: flex-end;
        justify-content: center;
        gap: 8px;
        height: 60px;
        margin-bottom: 20px;

        .volume-bar {
            width: 8px;
            background-color: #e0e0e0;
            border-radius: 4px;
            transition: background-color 0.2s;

            &.active {
                background-color: #07c160;
            }
        }
    }

    .recording-status {
        .status-text {
            font-size: 16px;
            color: #333;
        }
    }

    .recording-timer {
        font-size: 24px;
        font-weight: bold;
        color: #333;
        margin-bottom: 10px;
    }

    .recording-tip {
        font-size: 14px;
        color: #999;
    }
}
</style>